# src/net/crawler.py
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from urllib.parse import urljoin
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

from src.config import *
from src.utils.downloader import sanitize_filename


def fetch_all_servants(on_page_fetched=None, on_finished=None):
    """
    分页爬取全部英灵。
    - on_page_fetched(servants: list): 每爬取一页或初始时调用的回调函数。
    - on_finished(all_servants: list): 全部完成后调用的回调函数。
    """
    options = Options()
    options.add_argument("--headless")
    options.add_argument("--disable-gpu")
    options.add_argument("--no-sandbox")
    options.add_argument("--blink-settings=imagesEnabled=false")

    try:
        driver = webdriver.Chrome(options=options)
    except Exception as e:
        print("启动 ChromeDriver 失败：", e)
        return

    # 初始数据：先渲染3个提亚马特
    all_servants = list(TIAMAT_LIST)
    seen_ids = {s[0] for s in TIAMAT_LIST}
    if on_page_fetched:
        on_page_fetched(list(all_servants))

    try:
        url = urljoin(BASE_URL, "/w/英灵图鉴")
        driver.get(url)

        while True:
            # 等待当前页的表格加载
            WebDriverWait(driver, 10).until(
                EC.presence_of_element_located((By.ID, "lancelot_table_servantlist"))
            )

            table = driver.find_element(By.ID, "lancelot_table_servantlist")
            tbody = table.find_element(By.TAG_NAME, "tbody")
            rows = tbody.find_elements(By.TAG_NAME, "tr")[1:]

            page_servants = []
            for tr in rows:
                tds = tr.find_elements(By.TAG_NAME, "td")
                if len(tds) < 3:
                    continue
                servant_id = tds[0].text.strip()
                if servant_id in seen_ids:
                    continue

                name = tds[2].find_element(By.TAG_NAME, "a").text.strip()
                page_url = urljoin(BASE_URL, tds[1].find_element(By.TAG_NAME, "a").get_attribute("href"))
                icon_url = tds[1].find_element(By.TAG_NAME, "img").get_attribute("src")

                page_servants.append((servant_id, name, page_url, icon_url))
                seen_ids.add(servant_id)

            if page_servants:
                all_servants.extend(page_servants)
                if on_page_fetched:
                    # 每爬完一页就通知GUI更新
                    on_page_fetched(list(all_servants))

            # 查找并点击“下一页”
            try:
                # 显式等待“下一页”按钮可点击，使用ID进行定位
                next_btn = WebDriverWait(driver, 3).until(
                    EC.element_to_be_clickable((By.ID, "NextPage"))
                )
                # 使用JS点击以避免被遮挡
                driver.execute_script("arguments[0].click();", next_btn)
                # 等待旧表格消失，标志页面已开始跳转
                WebDriverWait(driver, 10).until(EC.staleness_of(rows[0]))
            except Exception:
                # 找不到或无法点击“下一页”，说明是最后一页
                break
    finally:
        driver.quit()
        if on_finished:
            on_finished(all_servants)


def fetch_servant_audios(page_url, return_pairs=False):
    """返回页面所有 mp3 链接；return_pairs=True 时返回 (url, filename)。"""
    options = Options()
    options.add_argument("--headless")
    options.add_argument("--disable-gpu")
    options.add_argument("--no-sandbox")
    options.add_argument("--blink-settings=imagesEnabled=false")
    driver = webdriver.Chrome(options=options)
    driver.get(page_url + "/语音")

    try:
        WebDriverWait(driver, 10).until(
            EC.presence_of_element_located((By.TAG_NAME, "a"))
        )
    except Exception:
        driver.quit()
        return []

    anchors = driver.find_elements("tag name", "a")
    results = []
    seen_titles = set()

    for a in anchors:
        try:
            href = a.get_attribute("href")
            if href and href.endswith(".mp3"):
                try:
                    tr = a.find_element(By.XPATH, "./ancestor::tr[1]")
                    th_text = tr.find_element(By.TAG_NAME, "th").text.strip()
                except Exception:
                    th_text = ""
                title = sanitize_filename(th_text)
                base_norm = title.lower()
                if base_norm == "untitled":
                    continue
                if base_norm in seen_titles:
                    continue
                seen_titles.add(base_norm)

                filename = f"{title}.mp3"
                if return_pairs:
                    results.append((href, filename))
                else:
                    results.append(href)
        except Exception:
            continue

    driver.quit()
    return results
